home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / ups < prev    next >
Encoding:
Internet Message Format  |  1988-01-31  |  22.8 KB

  1. Subject:  v13i066:  BSD File delivery programs, Part02/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Scooter Morris <scooter@genie.gene.com>
  7. Posting-number: Volume 13, Issue 66
  8. Archive-name: ups
  9.  
  10. [  Great name and concept, even if of unknown utility.  --r$ ]
  11.  
  12. This program allows users on 4.3bsd systems to pass around files in
  13. a manner very similar to mail.  It uses the network and the /usr/lib/aliases
  14. file to handle sending files to users on other machines.
  15.  
  16. #! /bin/sh
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create the files:
  21. #    README
  22. #    Makefile
  23. #    ups.c
  24. #    upsd.c
  25. #    ups.l
  26. export PATH; PATH=/bin:$PATH
  27. if test -f 'README'
  28. then
  29.     echo shar: will not over-write existing file "'README'"
  30. else
  31. cat << \SHAR_EOF > 'README'
  32. README for ups - the package delivery system
  33.  
  34. ups is a system (actually just two programs) for delivering files between
  35. users.  It works just like mail, except that accepting delivery implies
  36. the movement of files.  Basically, a user just types to the shell the
  37. following:
  38.     ups user file1 file2 ...
  39. this will cause the files file1, file2, ... to be copied into a spool area
  40. and a mail message to be sent to 'user' informing them that there are files
  41. awaiting them in ups.  To receive the files a user simply types 'ups' to
  42. the shell and gets a list of files which are awaiting delivery and is
  43. asked if they wish to accept delivery in the current directory.
  44.  
  45. What's required
  46.  
  47. ups was written for a 4.3bsd network of vaxes.  It will probably work on
  48. a 2.9 or 4.2 system without a lot of work.  Other machines will certainly
  49. require work.
  50.  
  51. Installation
  52.  
  53.     1)  Add ups to the table of known ports in /etc/services as follows:
  54.  
  55.     ups    600/tcp
  56.  
  57.     2)  Add ups to the inetd configuration file /etc/inetd.conf:
  58.  
  59.     ups    stream    tcp    nowait    root    /usr/local/lib/upsd    upsd
  60.  
  61.     3) Make ups and upsd by just saying "make all"
  62.     
  63.     4)  And finally install ups and upsd.  We installed upsd in /usr/local/lib 
  64.         (as shown above) and this is where make install will put it.
  65.          
  66.     We also added a line to our standard .login file of the form: ups -q.  This will 
  67.     inform users at login time if files are awaiting them.
  68.     
  69. SHAR_EOF
  70. fi # end of overwriting check
  71. if test -f 'Makefile'
  72. then
  73.     echo shar: will not over-write existing file "'Makefile'"
  74. else
  75. cat << \SHAR_EOF > 'Makefile'
  76. # $Header: Makefile,v 1.1 85/08/21 22:39:19 scooter Exp $
  77.  
  78. UPSDIR = "/usr/spool/ups"
  79. SENDMAIL = "/usr/lib/sendmail"
  80. BIN = "/usr/local/bin"
  81. LIB = "/usr/local/lib"
  82. # CFLAGS = -O -g -D'UPSDIR=$(UPSDIR)' -D'SENDMAIL=$(SENDMAIL)' -DDEBUG -DALIASES
  83. CFLAGS = -O -D'UPSDIR=$(UPSDIR)' -D'SENDMAIL=$(SENDMAIL)' -DALIASES
  84.  
  85. VPATH = ./RCS
  86. .SUFFIXES: .c,v
  87.  
  88. all:    ups upsd
  89.  
  90. install: ups upsd
  91.     cp ups $(BIN)/ups
  92.     cp upsd $(LIB)/upsd
  93.  
  94. .c,v.o:
  95.     co -q $*.c
  96.     cc $(CFLAGS) -c $*.c
  97.     mv $*.o OBJS
  98.     rm -f $*.c
  99.  
  100. ups:    ups.o
  101.     cc $(CFLAGS) -o ups ups.o
  102.  
  103. upsd:    upsd.o
  104.     cc $(CFLAGS) -o upsd upsd.o
  105. SHAR_EOF
  106. fi # end of overwriting check
  107. if test -f 'ups.c'
  108. then
  109.     echo shar: will not over-write existing file "'ups.c'"
  110. else
  111. cat << \SHAR_EOF > 'ups.c'
  112. #ifndef lint
  113. static char RCSid[] = "$Header: ups.c,v 1.8 86/12/11 15:58:18 scooter Exp $";
  114. #endif
  115.  
  116. /*
  117.  * ups - user interface to the package delivery system
  118.  *
  119.  * usage: ups user@host file1 file2 ...
  120.  *
  121.  * $Author: scooter $
  122.  * $Revision: 1.8 $
  123.  * $Date: 86/12/11 15:58:18 $
  124.  *
  125.  * $Log:    ups.c,v $
  126.  * Revision 1.8  86/12/11  15:58:18  scooter
  127.  * Added alias expansion code which allows ups to follow /usr/lib/aliases.
  128.  * 
  129.  * Revision 1.7  86/09/19  18:53:15  scooter
  130.  * Added -i option for mail specification
  131.  * 
  132.  * Revision 1.6  86/09/18  15:19:45  scooter
  133.  * More fixes to the '.' problam
  134.  * 
  135.  * Revision 1.5  86/09/17  09:43:38  scooter
  136.  * Added code to do automatic renaming of "." files for delivery to
  137.  * avoid the "cannot delete" problem
  138.  * 
  139.  * Revision 1.4  85/08/21  22:27:45  scooter
  140.  * Release revision: added more complete RCS headers.
  141.  * 
  142.  */
  143.  
  144. #include <stdio.h>
  145. #include <pwd.h>
  146. #include <ndbm.h>
  147. #include <sys/wait.h>
  148. #include <sys/types.h>
  149. #include <sys/stat.h>
  150. #include <sys/socket.h>
  151. #include <sys/file.h>
  152. #include <netinet/in.h>
  153. #include <netdb.h>
  154. #include <ctype.h>
  155.  
  156. #define    LS "/bin/ls"
  157.  
  158. struct    passwd *getpwuid();
  159. FILE     *fopen();
  160. int    rem;
  161. int    qflg = 0;
  162. int    iflg = 0;
  163. int    on   = 1;
  164. char    buffer[BUFSIZ*5];
  165. char    mbuffer[BUFSIZ*4];
  166.  
  167. struct    user_list {
  168.     char    *u_user;
  169.     char    *u_host;
  170.     struct    user_list *u_next;
  171. };
  172.  
  173. main(argc, argv)
  174. char **argv;
  175. int argc;
  176. {
  177.     char    myhost[BUFSIZ];
  178.     int    file;
  179.     int    ret;
  180.     char    *user,*host,*tmp,*rindex(),*index();
  181.     struct    passwd *mypwent;
  182.     struct    user_list *u_list,*u_top, *alias_expand();
  183.  
  184.     gethostname(myhost,BUFSIZ);
  185.  
  186.     if( (mypwent = getpwuid(getuid())) == NULL )
  187.     {
  188.         fprintf(stderr,"ups: who are you?\n");
  189.         exit(1);
  190.     }
  191.  
  192.     while (*argv[1] == '-')
  193.     {
  194.         char     c;
  195.  
  196.         switch (c = *(++argv[1]))
  197.         {
  198.  
  199.         case 'q':
  200.             qflg++;
  201.             break;
  202.  
  203.         case 'i':
  204.             iflg++;
  205.             break;
  206.  
  207.         default:
  208.             fprintf(stderr,"ups: unknown option %c\n",c);
  209.  
  210.         }
  211.         argv++;
  212.         argc--;
  213.     }
  214.  
  215.     if (argc == 1 || qflg)
  216.         upsread(mypwent);
  217.     
  218.     if (argc == 2) {
  219.         fprintf(stderr,"usage: ups user@host file1 file2 ...\n");
  220.         exit(0);
  221.     }
  222.  
  223. /*
  224.  * Get the name of the destination user and host
  225.  */
  226.  
  227.     user = argv[1];
  228.     host = rindex(user,'@');
  229. #ifndef    ALIASES
  230.     if (host == NULL)
  231.         host = myhost;
  232.     else
  233.         *host++ = '\0';
  234. #else
  235.     if (host != NULL)
  236.         *host++ = '\0';
  237.      
  238.     u_top = alias_expand(user,host,myhost);
  239.     
  240. #endif    ALIASES
  241.  
  242.     if (iflg)
  243.         upsgetmsg(mbuffer);
  244.     else
  245.         mbuffer[0] = '\0';
  246.  
  247.     while (u_top != NULL)
  248.     {
  249.  
  250. #ifdef    DEBUG
  251.     printf("Connecting to %s for user %s\n",u_top->u_host,u_top->u_user);
  252. #endif    DEBUG
  253.         rem = upsconnect(u_top->u_host);    /* Connect to the server */
  254.  
  255.         /*
  256.          * Send the to name, from name, and our name
  257.          */
  258.  
  259.         tmp = index(mypwent->pw_gecos,',');
  260.         if (tmp)
  261.             *tmp = '\0';
  262.  
  263.         sprintf(buffer, "%s\n%s\n%s\n%s", u_top->u_user,
  264.             mypwent->pw_name, mypwent->pw_gecos,mbuffer);
  265.  
  266. #ifdef    DEBUG
  267.     printf("Sending: %s\n",buffer);
  268.     fflush(stdout);
  269. #endif    DEBUG
  270.  
  271.         write(rem, buffer, strlen(buffer)+1);
  272.         ret = read(rem, buffer, BUFSIZ);
  273.         if (buffer[0])
  274.             problem(1);
  275.     
  276.         for (file = 2 ; file < argc ; file++)
  277.         {
  278.  
  279. #ifdef    DEBUG
  280.         printf("Sending file: %s",argv[file]);
  281. #endif    DEBUG
  282.  
  283.             sendfile(argv[file]);
  284.         }
  285.  
  286.         sprintf(buffer, "-Done-");
  287.         write(rem, buffer, strlen(buffer)+1);
  288.         read(rem, buffer, BUFSIZ);    /* get result */
  289.         if (buffer[0])        /* problem? */
  290.             problem(1);    /* yes, go handle it */
  291.  
  292.         close(rem);
  293.         u_top = u_top->u_next;
  294.      }
  295.  
  296. }
  297.  
  298.  
  299.  
  300.  
  301. upsconnect(host)
  302. char *host;
  303. {
  304.     struct hostent *hp;
  305.     struct servent *sp;
  306.     struct    sockaddr_in sin;
  307.     int s;
  308.  
  309.     hp = gethostbyname(host);
  310.     if (hp == NULL) {
  311.         static struct hostent def;
  312.         static struct in_addr defaddr;
  313.         static char namebuf[128];
  314.         int inet_addr();
  315.  
  316.         defaddr.s_addr = inet_addr(host);
  317.         if (defaddr.s_addr == -1) {
  318.             printf("unknown host: %s\n", host);
  319.             exit(1);
  320.         }
  321.         strcpy(namebuf, host);
  322.         def.h_name = namebuf;
  323.         def.h_addr = (char *)&defaddr;
  324.         def.h_length = sizeof (struct in_addr);
  325.         def.h_addrtype = AF_INET;
  326.         def.h_aliases = 0;
  327.         hp = &def;
  328.     }
  329.     sp = getservbyname("ups", "tcp");
  330.     if (sp == 0) {
  331.         fprintf(stderr,"tcp/ups: unknown service\n");
  332.         exit(1);
  333.     }
  334.     sin.sin_family = hp->h_addrtype;
  335.     bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
  336.     sin.sin_port = sp->s_port;
  337.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  338.     if (s < 0) {
  339.         fflush(stderr);
  340.         perror("ups (socket)");
  341.         exit(1);
  342.     }
  343.     setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&on,sizeof(on));
  344. #ifdef    DEBUG
  345.     setsockopt(s,SOL_SOCKET,SO_DEBUG,&on,sizeof(on));
  346. #endif    DEBUG
  347.     if (connect(s, (char *)&sin, sizeof (sin)) < 0) {
  348.         fflush(stderr);
  349.         perror("ups (connect)");
  350.         close(s);
  351.         exit(1);
  352.     }
  353.     return(s);
  354. }
  355.  
  356.  
  357.  
  358.  
  359. sendfile(file)
  360. char *file;
  361. {
  362.     struct    stat fstatus;
  363.     int    loc,n;
  364.     char    *tmp,*fname;
  365.  
  366.     if ( (loc = open(file,O_RDONLY)) <= 0 ) {
  367.         perror("ups (open)");
  368.         return(1);
  369.     }
  370.     if (fstat(loc, &fstatus)) {
  371.         perror("ups (fstat)");
  372.         return(1);
  373.     }
  374.  
  375.     if ((fstatus.st_mode&S_IFMT) != S_IFREG) {
  376.         switch (fstatus.st_mode&S_IFMT)
  377.         {
  378.         case S_IFDIR:
  379.             tmp = "directory";
  380.             break;
  381.         case S_IFCHR:
  382.             tmp = "character device";
  383.             break;
  384.         case S_IFBLK:
  385.             tmp = "block device";
  386.             break;
  387.         case S_IFLNK:
  388.             tmp = "symbolic link";
  389.             break;
  390.         case S_IFSOCK:
  391.             tmp = "socket";
  392.             break;
  393.         }
  394.  
  395.         fprintf(stderr,
  396.             "ups: %s is a %s, only regular files may be sent\n",
  397.             file,tmp);
  398.         fflush(stderr);
  399.         return(1);
  400.     }
  401.  
  402.     /*
  403.      * Send the file name
  404.      */
  405.  
  406.     /*
  407.      * First strip off the directory path
  408.      */
  409.     sprintf(buffer,"%s",file);
  410.     tmp = rindex(buffer,'/');
  411.     if (tmp) 
  412.         *tmp++ = '\0';
  413.     else
  414.         tmp = buffer;
  415.  
  416.     fname = tmp;
  417.  
  418.     if (*tmp == '.')
  419.     {
  420.         while ( (*tmp == '.') && (*tmp != '\0') )tmp++;
  421.  
  422.         fprintf(stdout,
  423.           "WARNING: file %s has been renamed to %s for delivery\n",
  424.           fname,tmp);
  425.     }
  426.  
  427.     write(rem, tmp, strlen(tmp)+1);
  428.     read(rem, buffer, BUFSIZ);
  429.     if (buffer[0])        /* problem */
  430.     {
  431.         problem(0);
  432.         return(1);
  433.     }
  434.  
  435.     /*
  436.      * Send the file size in bytes
  437.      */
  438.  
  439.     sprintf(buffer, "%D",fstatus.st_size);
  440.     write(rem, buffer, strlen(buffer)+1);
  441.     read(rem, buffer, BUFSIZ);
  442.     if (buffer[0])        /* problem */
  443.     {
  444.         problem(0);
  445.         return(1);
  446.     }
  447.  
  448.     /*
  449.      * Send the file
  450.      */
  451.     while (n = read(loc, buffer, BUFSIZ))
  452.         write(rem, buffer, n);
  453.     close(loc);
  454.     read(rem, buffer, BUFSIZ); /* get result */
  455.     if (buffer[0])        /* problem */
  456.     {
  457.         problem(0);
  458.         return(1);
  459.     }
  460.     sprintf(buffer, "%u", fstatus.st_mode);
  461.     write(rem, buffer, strlen(buffer)+1);
  462.     read(rem, buffer, BUFSIZ); /* get result */
  463.     if (buffer[0])        /* problem */
  464.     {
  465.         problem(0);
  466.         return(1);
  467.     }
  468.     return(0);
  469. }
  470.  
  471.  
  472.  
  473. upsread(mypwent)
  474. struct    passwd *mypwent;
  475. {
  476.     union    wait status;
  477.     int    pid;
  478.     char    c,line[BUFSIZ],*tmp;
  479.  
  480.     sprintf(buffer,"%s/%s",UPSDIR,mypwent->pw_name);
  481.     if (qflg)
  482.     {
  483.         if (!access(buffer,F_OK)) {
  484.         fprintf(stderr,
  485.     "You have ups files awaiting you (type ups to accept delivery)\n");
  486.         }
  487.         exit(0);
  488.     }
  489.     if (access(buffer,F_OK)) {
  490.         fprintf(stderr,"Nothing waiting in ups\n");
  491.         exit(0);
  492.     }
  493.     fprintf(stdout,"\nYou have the following files awaiting delivery:\n\n");
  494.     if (pid = vfork())
  495.     {
  496.         wait(&status);
  497.     } else {
  498.         execl(LS,"ls","-C",buffer,(char *)0);
  499.         perror("ups (exec)");
  500.         return(0);
  501.     }
  502.     fprintf(stdout,"\n");
  503.  
  504.     fprintf(stdout,
  505.         "Do you wish to accept delivery in your\n");
  506.     fprintf(stdout,
  507.         "current directory (%s)? ",
  508.         getwd(line));
  509.  
  510. getinp:
  511.     if (fgets(line,BUFSIZ,stdin) == NULL) {
  512.         fprintf(stdout,"\n");
  513.         exit(0);
  514.     }
  515.  
  516.     tmp = &line[0];
  517.     while (isspace(*tmp)) tmp++;
  518.  
  519.     switch (*tmp) {
  520.     case 'y':
  521.     case 'Y':
  522.         sprintf(line,"mv -i %s/* . ; rmdir %s",buffer,buffer);
  523.         system(line);
  524.         exit(0);
  525.  
  526.     case 'n':
  527.     case 'N':
  528.         exit(0);
  529.  
  530.     default:
  531.         fprintf(stdout,"Please answer 'yes' or 'no': ");
  532.         goto getinp;
  533.     }
  534. }
  535.  
  536.  
  537.  
  538. /*
  539.  * problem() is called when the install demon process return a non-zero reply.
  540.  * This usually means something recognizable went wrong and we should expect
  541.  * a reason to follow. Read in the reason, output it on the terminal and die.
  542.  */
  543.  
  544. problem(die)
  545. int die;
  546. {
  547.     char buf[BUFSIZ];    /* place to read into */
  548.  
  549.     if (read(rem, buf, BUFSIZ) > 0)        /* if we have something */
  550.         fprintf(stderr, "ups: %s", buf);
  551.     if (die) {
  552.         close(rem);        /* close network channel */
  553.         exit(1);
  554.     }
  555. }
  556.  
  557. int
  558. upsgetmsg(mailbuffer)
  559. char *mailbuffer;
  560. {
  561.     int done = 0;
  562.  
  563.     fprintf(stdout,
  564.         "Enter your message followed by '.<RETURN>' or a <CTRL>D:\n");
  565.     
  566.     while (!done)
  567.     {
  568.         fprintf(stdout,"> ");
  569.         if (gets(mailbuffer) == NULL)
  570.         {
  571.             fprintf(stdout,"\n");
  572.             done++;
  573.         } else if ( (*mailbuffer == '.') && (*(mailbuffer+1) == '\0')) 
  574.         {
  575.             done++;
  576.             *mailbuffer = '\0';
  577.         } else {
  578.             while(*mailbuffer != '\0')
  579.                 mailbuffer++;
  580.             *mailbuffer++ = '\n';
  581.             *mailbuffer = '\0';
  582.         }
  583.     }
  584.     fprintf(stdout,"[EOT]\n");
  585. }
  586.  
  587.  
  588.  
  589. struct user_list *
  590. alias_expand(user,host,myhost)
  591. char *user,*host,*myhost;
  592. {
  593.     char    *malloc();
  594.     DBM    *dp;
  595.     datum    key,content;
  596.     struct    user_list *list,*top,*alloc_list();
  597.     char    *cp,*tp,*hp;
  598.     
  599.     list = top = (struct user_list *)NULL;
  600.  
  601.     if (host != NULL)
  602.         return(alloc_list(user,host));
  603.         
  604.     dp = dbm_open("/usr/lib/aliases", O_RDONLY, 0644);
  605.     if (dp == NULL)
  606.         return(alloc_list(user,host));
  607.     
  608.     key.dptr = user;
  609.     key.dsize = strlen(user) + 1;
  610.     
  611.     content = dbm_fetch(dp,key);
  612.     if (content.dptr == NULL)
  613.         return(alloc_list(user,myhost));
  614.     cp = content.dptr;
  615.     while (cp != NULL)
  616.     {
  617.         tp = cp;
  618.         cp = index(cp,',');
  619.         if (cp != NULL)
  620.             *cp++ = '\0';
  621.         if (index(tp,'!')) {
  622.           fprintf(stderr,
  623.              "ups: WARNING: cannot alias %s to %s (no ups over uucp)\n",
  624.               user,hp);
  625.           continue;
  626.         } else if(index(tp,'|')) {
  627.           fprintf(stderr,
  628.              "ups: WARNING: cannot alias %s to %s (no shells allowed)\n",
  629.               user,hp);
  630.           continue;
  631.         }
  632.         hp = tp;
  633.         hp = index(tp,'@');
  634.         if (hp == NULL)
  635.             hp = myhost;
  636.         else
  637.             *hp++ = '\0';
  638.         if (top == NULL)
  639.             top = list = alloc_list(tp,hp);
  640.         else
  641.         {
  642.             list->u_next = alloc_list(tp,hp);
  643.             list = list->u_next;
  644.         }
  645.     }
  646.     return(top);
  647. }
  648.  
  649. struct    user_list *
  650. alloc_list(user,host)
  651. char *user,*host;
  652. {
  653.     char *malloc();
  654.     struct    user_list *list;
  655.  
  656.     list = (struct user_list *)malloc(sizeof(struct user_list));
  657.     list->u_user = malloc(strlen(user) + 1);
  658.     list->u_host = malloc(strlen(host) + 1);
  659.     strcpy(list->u_user,user);
  660.     strcpy(list->u_host,host);
  661.     list->u_next = (struct user_list *)NULL;
  662.     return(list);
  663. }
  664. SHAR_EOF
  665. fi # end of overwriting check
  666. if test -f 'upsd.c'
  667. then
  668.     echo shar: will not over-write existing file "'upsd.c'"
  669. else
  670. cat << \SHAR_EOF > 'upsd.c'
  671. #ifndef lint
  672. static char RCSid[] = "$Header: upsd.c,v 1.4 86/11/19 15:21:52 scooter Exp $";
  673. #endif
  674.  
  675. /*
  676.  * upsd - package delivery server
  677.  *
  678.  * upsd is the program that is called by inetd when a ups
  679.  * request is issued.  It will read and write to standard input
  680.  * and standard output.  Here is a description of the ups
  681.  * protocol:
  682.  *
  683.  *     ups            upsd                    type
  684.  *
  685.  *  user_name    ------>        login name of package receiver        String
  686.  *  from_name    ------>        login name of package sender        String
  687.  *  full_name    ------>        full name of package sender        String
  688.  *  message    ------>        mail message to send            String
  689.  *        <-----        0 for OK                Byte
  690.  * For each file:
  691.  *  file_name    ------>        name of file to be delivered        String
  692.  *  file_size    ------>        size of file in bytes            Long
  693.  *        <-----        0 for OK                Byte
  694.  *  file    ------>        file size bytes
  695.  *        <-----        0 for OK                Byte
  696.  *  file_mode    ------>        file mode                Int
  697.  *        <-----        0 for OK                Byte
  698.  *
  699.  * When its all done:
  700.  *  complete    ------>        We're done ('-Done-')            String
  701.  *        <-----        0 for OK                Byte
  702.  *
  703.  * $Author: scooter $
  704.  * $Revision: 1.4 $
  705.  * $Date: 86/11/19 15:21:52 $
  706.  *
  707.  * $Log:    upsd.c,v $
  708.  * Revision 1.4  86/11/19  15:21:52  scooter
  709.  * Changed error severity level from ERR to INFO
  710.  * 
  711.  * Revision 1.3  86/09/19  18:53:37  scooter
  712.  * Added -i option for mail specification.
  713.  * Also added syslog stuff.
  714.  * 
  715.  * Revision 1.2  85/08/21  22:28:11  scooter
  716.  * Release revision: added more complete RCS headers.
  717.  * 
  718.  *
  719.  */
  720.  
  721. #include    <stdio.h>
  722. #include    <pwd.h>
  723. #include    <grp.h>
  724. #include    <sys/file.h>
  725. #include    <sys/types.h>
  726. #include    <netinet/in.h>
  727. #include    <netdb.h>
  728. #include    <syslog.h>
  729.  
  730. long    atol();
  731. int    atoi();
  732.  
  733. char    buffer[BUFSIZ*5];    /* character input buffer */
  734. char    file_name[BUFSIZ];    /* file name */
  735. char    file_path[BUFSIZ];    /* full path to destination */
  736. char    user_name[BUFSIZ];    /* Receiver name */
  737. char    from_name[BUFSIZ];    /* Sender name */
  738. char    full_name[BUFSIZ];    /* Full name of sender */
  739. char    file_list[BUFSIZ];    /* List of all files */
  740. long    file_size;        /* number of bytes in file */
  741. int    file_mode;        /* mode of the file */
  742. char    mail_message[BUFSIZ*4];    /* mail message */
  743. int    mcount;            /* number of characters in mail buffer */
  744.  
  745. int    fid;            /* File descriptor for destination */
  746. int    debugflag;        /* Debug flag */
  747.  
  748. main(argc, argv)
  749. int argc;
  750. char **argv;
  751. {
  752.     char *ptr,*tptr,*mptr;
  753.     int f, i, file;
  754.     struct sockaddr_in sin;
  755.     struct hostent *peer;
  756.     struct passwd *pwent;
  757.     
  758.     while (*argv[1] == '-')
  759.     {
  760.         char     c;
  761.  
  762.         switch (c = *(++argv[1]))
  763.         {
  764.  
  765.         case 'd':
  766.             debugflag++;
  767.             break;
  768.  
  769.         default:
  770.             fprintf(stderr,"upsd: unknown option %c\n",c);
  771.  
  772.         }
  773.         argv++;
  774.         argc--;
  775.     }
  776.     
  777.  
  778.     openlog("upsd",LOG_ODELAY,LOG_DAEMON);
  779.     
  780.     if (debugflag)
  781.         syslog(LOG_DEBUG,"started");
  782.     
  783.     i = sizeof (sin);
  784.     if (getpeername(0, &sin, &i) < 0)
  785.         syslog(LOG_ERR,"getpeername failed: %m");
  786.  
  787.     if (debugflag)
  788.         syslog(LOG_DEBUG,"Calling gethostbyaddr");
  789.     
  790.     peer = gethostbyaddr((char *)&sin.sin_addr,
  791.                 sizeof(sin.sin_addr),sin.sin_family);
  792.  
  793.     buffer[0] = '\0';
  794.     file_list[0] = '\0';
  795.  
  796.     if (debugflag)
  797.         syslog(LOG_DEBUG,"Reading first buffer");
  798.  
  799.     read(0, buffer, BUFSIZ*5);  /* fetch receiver and sender names */
  800.  
  801.     if (debugflag)
  802.         syslog(LOG_DEBUG,"receiver/sender/message: %s",buffer);
  803.  
  804.     ptr = buffer;
  805.     while (*ptr != '\n')
  806.         ptr++;
  807.     *ptr++ = NULL;
  808.     strcpy(user_name, buffer);    /* save receiver name */
  809.     tptr = ptr;
  810.     while (*tptr != '\n')
  811.         tptr++;
  812.     *tptr++ = NULL;
  813.     strcpy(from_name, ptr);        /* save sender name */
  814.     mptr = tptr;
  815.     while ((*mptr != '\n') && (*mptr != '\0'))
  816.         mptr++;
  817.     *mptr++ = NULL;
  818.     strcpy (full_name, tptr);    /* save sender's full name */
  819.     strcpy (mail_message, mptr);    /* save the mail message */
  820.  
  821.     /*
  822.      * Check for a valid user
  823.      */
  824.     if ((pwent = getpwnam(user_name)))
  825.         ack();
  826.     else
  827.     {
  828.         error("Receiver name","No such person");
  829.         exit(1);
  830.     }
  831.     
  832.     mcount = strlen (mail_message);
  833.     if (debugflag)
  834.         syslog(LOG_DEBUG,"mail message (%d chars):\n %s", mcount, mail_message);
  835.  
  836.     for (file = 0 ;;)
  837.     {
  838.         if (read(0, buffer, BUFSIZ) <= 0) {
  839.             error("file name","premature EOF or file read error");
  840.             continue;
  841.         }
  842.         strcpy(file_name,buffer);
  843.  
  844.         if (debugflag)
  845.             syslog(LOG_DEBUG,"File name:%s",file_name);
  846.  
  847.  
  848.         /*
  849.          * Are we done??
  850.          */
  851.         if (!strncmp(file_name,"-Done-",6)) break;
  852.  
  853.         if ( (fid = opendest(user_name,file_name,
  854.                 pwent->pw_uid,pwent->pw_gid)) <= 0 ) 
  855.         {
  856.             continue;
  857.         }
  858.         ack();
  859.  
  860.         if (read(0, buffer, BUFSIZ) <= 0) {
  861.             error("file size","premature EOF or file read error");
  862.             continue;
  863.         }
  864.  
  865.         file_size = atol(buffer); /* get number of bytes */
  866.         ack();
  867.  
  868.         copyfile(&file);
  869.  
  870.         if (read(0, buffer, BUFSIZ) <= 0) {
  871.             error("file mode","premature EOF or file read error");
  872.             continue;
  873.         }
  874.         file_mode = atoi(buffer);     /* get the file mode */
  875.         file_mode &= 0700;        /* Strip the low order modes */
  876.         if (chmod(file_path,file_mode)) {
  877.             error("file mode","chmod failed");
  878.             continue;
  879.         }
  880.         ack();
  881.         chown(file_path,pwent->pw_uid,pwent->pw_gid);
  882.  
  883.     }
  884.     ack();
  885.  
  886.     if (file)
  887.         sendmail(from_name,full_name,peer->h_name,
  888.               user_name,file_list,file++,mail_message,mcount);
  889. }
  890.  
  891. /*
  892. copyfile
  893. copyfile will copy file_size many bytes from stdin to a temporarily created
  894. file. The filename will be passed back via buffer.
  895. */
  896.  
  897. copyfile(file)
  898. int *file;
  899. {
  900.     long cnt;                /* file size counter */
  901.     int i;
  902.  
  903.     cnt = file_size;        /* count down input bytes */
  904.     while (cnt > 0) {
  905.         i = read(0, buffer, BUFSIZ);
  906.         write(fid, buffer, i);
  907.         cnt -= i;
  908.     }
  909.     close(fid);
  910.  
  911.     ack();
  912.     sprintf(buffer,"%-15s",file_name);
  913.     if (*file%4)
  914.         strcat(file_list," ");
  915.     else
  916.         strcat(file_list,"\n\t");
  917.  
  918.     (*file)++;
  919.     strcat(file_list,buffer);
  920. }
  921.  
  922. /*
  923. error(option, string)
  924. char *option, *string;
  925. This routine is called when some error condition has been encountered.
  926. option contains an identifier message, while string contains the actual
  927. error message. Before message is printed, a non-null character is output
  928. first, then the string error message.
  929. */
  930.  
  931. error(option, string)
  932. char *option, *string;
  933. {
  934.     char buf[BUFSIZ];
  935.  
  936.  
  937.     buf[0] = 1;
  938.     write(1, buf, 1);    /* nak */
  939.     sprintf(buf, "upsd: %s: %s\n", option, string);
  940.     write(1, buf, strlen(buf)+1);
  941.  
  942.     syslog(LOG_INFO,"error - %s",buf);
  943. }
  944.  
  945.  
  946.  
  947. /*
  948.  * ack()
  949.  * This routine is called to return an OK to the remote host.
  950.  */
  951.  
  952. ack()
  953. {
  954.     buffer[0] = 0;
  955.     write(1,buffer,1);
  956. }
  957.  
  958.  
  959.  
  960. /*
  961.  * opendest(name,file)
  962.  * char *name,*file;
  963.  *
  964.  * Open the destination file "file" in UPSDIR/user, creating the
  965.  * file if necessary.
  966.  */
  967.  
  968. int
  969. opendest(name,file,uid,gid)
  970. char *name,*file;
  971. int uid,gid;
  972. {
  973.     int ret;
  974.  
  975.     sprintf(file_path,"%s/%s",UPSDIR,name); /* Form path to directory */
  976.  
  977.     if (access(file_path,F_OK) == (-1))
  978.     {
  979.         mkdir(file_path,0700);
  980.         chown(file_path,uid,gid);
  981.     }
  982.  
  983.     sprintf(file_path,"%s/%s/%s",UPSDIR,name,file);
  984.  
  985.     if (!access(file_path,F_OK))
  986.     {
  987.         error("file creation","A file by that name has already been sent to that user.");
  988.         return(0);
  989.     } else {
  990.         ret = open(file_path,O_WRONLY|O_CREAT,0600);
  991.         if (ret <= 0)
  992.         {
  993.             sprintf(buffer,"unable to open destination file: %s",
  994.                 file_path);
  995.             error("file open",buffer);
  996.             return(0);
  997.         }
  998.         return(ret);
  999.     }
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /*
  1005.  * sendmail(from,full,from_host,to,list,mess,count)
  1006.  * char *from,*full,*to,*from_host,*list,*mess;
  1007.  * int    count;
  1008.  *
  1009.  * This routine sends mail to the destination user to inform
  1010.  * them that ups files are awaiting them.
  1011.  */
  1012.  
  1013. sendmail(from,full,from_host,to,list,file,mess,count)
  1014. char *from,*full,*to,*from_host,*list,*mess;
  1015. int file,count;
  1016. {
  1017.     FILE *send,*popen();
  1018.     static char myhost[BUFSIZ];
  1019.  
  1020.     gethostname(myhost,BUFSIZ);
  1021.     sprintf(buffer,"%s -f%s@%s -F\"%s\" -t",SENDMAIL,from,from_host,full);
  1022.  
  1023.     if(debugflag)
  1024.         syslog(LOG_DEBUG,"sendmail\n%s",buffer);
  1025.  
  1026.     send = popen(buffer,"w");
  1027.  
  1028.     fprintf(send,"To: %s@%s\n",to,myhost);
  1029.  
  1030.     if(debugflag)
  1031.         syslog(LOG_DEBUG,"To: %s@%s",to,myhost);
  1032.  
  1033.     fprintf(send,"Subject: UPS delivery\n");
  1034.     if (file > 1)
  1035.         strcpy(buffer,"files");
  1036.     else
  1037.         strcpy(buffer,"file");
  1038.  
  1039.     fprintf(send,"I have sent you the following %s using ups:\n",buffer);
  1040.     fprintf(send,"%s\n\n",list);
  1041.     if (file > 1)
  1042.         strcpy(buffer,"these files");
  1043.     else
  1044.         strcpy(buffer,"this file");
  1045.         
  1046.     fprintf(send,"To retrieve %s, use the ups command.\n\n\n",buffer);
  1047.     if (count)
  1048.         fprintf(send,"%s\n",mess);
  1049.     else
  1050.         fprintf(send,"\n\n\n\n---ups\n");
  1051.     pclose(send);
  1052. }
  1053. SHAR_EOF
  1054. fi # end of overwriting check
  1055. if test -f 'ups.l'
  1056. then
  1057.     echo shar: will not over-write existing file "'ups.l'"
  1058. else
  1059. cat << \SHAR_EOF > 'ups.l'
  1060. .TH UPS LOCAL
  1061. .UC 2
  1062. .SH NAME
  1063. ups \- send files to another user
  1064. .SH SYNOPSIS
  1065. .B ups [\-i]
  1066. user[@host]
  1067. file(s)
  1068. .br
  1069. .B ups
  1070. .br
  1071. .B ups \-q
  1072. .SH DESCRIPTION
  1073. The first form of the command
  1074. sends copies of files to another user.
  1075. The specified files are copied
  1076. into a special spool directory until the receiver
  1077. retrieves them.
  1078. The receiver is notified via \fImail\fR that the files are waiting.
  1079. .PP
  1080. The receiver of the files is specified by typing his/her
  1081. login id.  If you don't know the login id of the receiver,
  1082. type \fIfinger\fR, space, followed by the name of the receiver.
  1083. For example, typing \fIfinger polly\fR would give information,
  1084. including login name, for all users named "polly", and
  1085. \fIfinger polly@genie\fR would give information, including login
  1086. name, for all users named "polly" on the machine "genie".  If the
  1087. user you were interested in sending files to had the login name "pam"
  1088. you could send her files using the command:
  1089. .IP
  1090. \fIups pam@genie file1 ~ckw/file2\fR
  1091. .PP
  1092. This command will send the two files to \fIpam\fR.
  1093. .PP
  1094. The
  1095. .B \-i
  1096. flag is used when the user wishes to interactively specify their own
  1097. message to be appended to the mail sent to the receiver.
  1098. .PP
  1099. The second form of the command is used to receive the files
  1100. awaiting delivery in the spool directory.  The user is shown
  1101. what files are available and asked if he/she wants to accept
  1102. delivery.  If the user accepts delivery, all of the files
  1103. are moved into the current directory.
  1104. .PP
  1105. The third form of the command simply tells the user if there are any
  1106. files waiting.
  1107. .SH SEE ALSO
  1108. ftp(1c), rcp(1), finger(1)
  1109. SHAR_EOF
  1110. fi # end of overwriting check
  1111. #    End of shell archive
  1112. exit 0
  1113.